﻿function RegisterNamespace(ns) { var p = ns.split('.'); var r = self; for (var i = 0, j; j = p[i], i < p.length; r.__namespace = true, i++) r = r[j] || (r[j] = {}); return r; }

(function ($, ns) {
    if (!$) {
        throw new Error("PageGrid需要jQuery库支持");
    }
    // 折叠或展开控件
    ns.Toggle = function(pageGridClientID, toggler){
        $('tr','#' + pageGridClientID).not('.pg-header, .pg-data-selected').toggle();
        $(toggler).toggleClass("pg-toggler-collapsed");
    }
    /**
    * 执行表格全选取消选择功能，查询该列中存在的checkbox进行关联选择
    *    this   触发全选的checkbox对象
    */
    ns.CheckColumn = function () {
        var handle = $(this);
        var column = handle.parentsUntil(document.body, "td");
        var columnIndex = column.prevAll('td').length;
        var grid = handle.parentsUntil(document.body, "table");
        var rows = grid.find("tr");
        var checked = handle.attr("checked")
        for (var i = 1/*ignore header*/; i < rows.length/* ignore footer*/; i++) {
            var checkboxs = $(rows[i]).find("td").eq(columnIndex).find(":checkbox");
            if (checked) checkboxs.attr("checked", checked);
            else checkboxs.removeAttr("checked");
        }
    }

    /*
    * 获取选择的CheckBox
    */
    ns.GetChecked = function (gridDom, columnIndex) {
        var rows = $(gridDom).find("tr");
        var currentColumnIndex = 0;
        var headers = $(rows).get(0).cells;
        for (var currentColumnIndex = 0; currentColumnIndex < headers.length; currentColumnIndex++)
            if ($(headers[currentColumnIndex]).attr('id') == columnIndex.toString()) break;

        var checkboxs = [];
        for (var i = 1/*ignore header*/; i < rows.length; i++) {
            var checkbox = $(rows[i]).find("td").eq(currentColumnIndex).find(":checkbox:checked");
            if (checkbox.length) {
                checkboxs.push(checkbox.get(0));
            }
        }
        return checkboxs;
    }
    /*
    * 获取选择行的ID数组
    */
    ns.GetCheckedID = function (gridDom, columnIndex) {
        var checked = SK.Grid.GetChecked(gridDom, columnIndex);
        var ids = [];
        for (var i = 0; i < checked.length; i++) {
            ids.push($(checked[i]).attr('id'));
        }
        return ids;
    }

    /**
    * 表头存储
    */
    function ColumnOrderStorage() {
        this.getStorePath = function () {
            var match = location.href.match(/([^\/\?]+)($|\/$|\?)/);
            return match[1].toString().replace(/[^0-9A-Z\_]/ig, '');
        }

        this.isOrignal = function (orders) {
            for (var i = 0; i < orders.length; i++) {
                if (i != orders[i]) return false;
            }
            return true;
        }

        this.restore = function (grid) {
            var storeName = this.getStorePath() + grid.attr('id');
            var regex = new RegExp('(^||;)' + storeName + '=([^;$]+)');
            var store = document.cookie.match(regex);
            if (store && store.length) {
                var orders = (store[2]).split(',');
                grid.find('tr').each(function () {
                    if (this.cells.length != orders.length/*不一致忽略*/) return;
                    var cells = [];
                    $("td", this).each(function () {
                        cells.push(this);
                        $(this).remove();
                    });
                    for (var i = 0; i < cells.length; i++) {
                        $(this).append(cells[orders[i]]);
                    }
                });
            }
        }
        this.save = function (grid) {
            var orders = [];
            grid.find("tr:first").find('td').each(function () {
                orders.push(parseInt($(this).attr("id")));
            });
            var storeName = this.getStorePath() + grid.attr('id');
            var expires = new Date();
            expires.setTime(this.isOrignal(orders) ? expires.getTime() - 24 * 60 * 60
                    : expires.getTime() + 365 * 24 * 60 * 60 * 1000/*365天*/);
            document.cookie = storeName + '=' + (orders.join(',')) + ';expires=' + expires.toGMTString() + ';';
        }
    }
    /***********  表头合并处理   ***************/
    /*  探测当前列的根ID 
     *    this 指向当前列
     *    grid  TABLE DOM对象
     */
    function detectGroupingRootID(grid){
      var groupingParent = $(this).attr('data-grouping');
      if(groupingParent == undefined){
          return -1;
      }
      if(groupingParent == $(this).attr('id')){
        return groupingParent;
      }
      var parent = $('tr:first td[id=' + groupingParent + ']:first', grid);
      if(!parent.length) throw new Error('Grouping未找到：' + groupingParent);
      var root = detectGroupingRootID.call(parent, grid);
      return (root == -1 ? groupingParent : root);
    }
    /**
     *  this  指向当前Table的DOM对象
     */
    function gridGrouping(){
      var header = $('tr:first td[data-grouping]', this);
      if(this.rows.length < 3 || header.length == 0) return;
      $(this).data('groupingStack', []);
      var grid = this;
      var processed = [];
      header.each(function(){
        var rootIndex = detectGroupingRootID.call(this, grid);
        if(rootIndex != -1 && $.inArray(rootIndex, processed) == -1){
          gridColumnGrouping.call(grid, rootIndex, 1, grid.rows.length);
          processed.push(rootIndex);
        }
      });
      $('td[grouping-deleted]').remove();
      $(this).removeData('groupingStack');
    }
    /** 分组列入栈
     * this 指向当前Table的DOM对象
     */
    function pushGroupingColumn(columnID){
      var stack = $(this).data("groupingStack");
      if(!stack) throw new Error('分组检查栈未初始化')
      if($.inArray(columnID, stack) != -1) throw new Error('递归异常: 对象已经存在于分组堆栈中');
      stack.push(columnID);
    }
    
    /** 分组列出栈
     * this 指向当前Table的DOM对象
     */
    function popGroupingColumn(){
      var stack = $(this).data("groupingStack");
      stack.pop();
    }
    /* 列分组
     *  this 指向当前Table的DOM对象
     *  columnID  当前合并列
     *  from      起始行
     *  to        结束行
     */
    function gridColumnGrouping(columnID, from, to){
      var index = $('tr:first td', this).index($('tr:first td[id=' + columnID + ']:first', this));
            
      pushGroupingColumn.call(this, columnID);
      var previous = $(this.rows[from].cells[index]), previousIndex = from;
      for(var i = from + 1; i < to; i ++){
        var current = $(this.rows[i].cells[index]).attr('grouping-deleted', true);
        if(current.text() != previous.text()){
          previous.attr('rowspan', i - previousIndex);
          groupingReferenceColumns.call(this, columnID, previousIndex, i);
          previous = current.removeAttr('grouping-deleted');
          previousIndex = i;
        } else if(i == to - 1) {
          previous.attr('rowspan', to - previousIndex);
          groupingReferenceColumns.call(this, columnID, previousIndex, to);
        }
      }
      popGroupingColumn.call(this);
    }
    
    /**
     * 处理关联列
     *  this   当前TABLE DOM对象
     *  refrenceID  当前合并列
     *  from      起始行
     *  to        结束行
     */
    function groupingReferenceColumns(refrenceID, from, to){
      var grid = this;
      $('tr:first td[data-grouping=' + refrenceID + ']', grid ).each(function(){
        gridColumnGrouping.call(grid, $(this).attr('id'), from, to);
      });
    }

    ns.Grouping = function(gridID){
        var grid = $("#" + gridID);
        if(grid.length) gridGrouping.call(grid[0]);
    };

    /***********  表头列移动处理 **************/
    var adjudsting = null;  /*正在进行移动的列*/
    var adjustingGrid = null;
    var adjustingHeader = null;
    var shadow = null;
    var startClientX;
    var prevStartClientX;
    var nextStartClientX;
    var adjustingPosition;
    var prevSwapOffset;
    var nextSwapOffset;
    var adjustingIndex = 0;
    var columnOrderStorage = new ColumnOrderStorage();

    function cancelSelect() { return false; }

    function doAdjustColumn(e) {
        if (e.which != 1) return endAdjustColumn();
        $(adjudsting).addClass("grid-header-moving");
        if (shadow == null) {
            adjustingPosition = $(adjudsting).position();
            shadow = $('<div class="grid-shadow">&nbsp;</div>')
                            .appendTo(document.body)
                            .css('height', adjustingGrid.height() - 2)
                            .css('width', $(adjudsting).width())
                            .css(adjustingPosition);
        } else {
            if (shadow) {
                $(shadow).css("left", e.clientX - startClientX + adjustingPosition.left);
                if (e.clientX - nextStartClientX > nextSwapOffset) doNextSwap(e);
                else if (e.clientX - prevStartClientX < -prevSwapOffset) doPreviousSwap(e);
            }
        }
    }

    function doPreviousSwap(e) {
        var prev = $(adjudsting).prev("td");
        if (prev.length) {
            $(adjudsting).insertBefore(prev);
            prevSwapOffset += prev.width();
            nextSwapOffset = 15;
            nextStartClientX = e.clientX;
            var rows = adjustingGrid.get(0).rows;
            for (var i = 1; i < rows.length; i++) {
                if ($(rows[i]).hasClass('grid-footer')) continue;
                $(rows[i].cells[adjustingIndex]).insertBefore(rows[i].cells[adjustingIndex - 1]);
            }
            columnOrderStorage.save(adjustingGrid);
            adjustingIndex--;
        }
    }

    function doNextSwap(e) {
        var next = $(adjudsting).next("td");
        if (next.length) {
            next.insertBefore(adjudsting);
            nextSwapOffset += next.width();
            prevSwapOffset = 15;
            prevStartClientX = e.clientX;
            var rows = adjustingGrid.get(0).rows;
            for (var i = 1; i < rows.length; i++) {
                if ($(rows[i]).hasClass('grid-footer')) continue;
                $(rows[i].cells[adjustingIndex + 1]).insertBefore(rows[i].cells[adjustingIndex]);
            }
            columnOrderStorage.save(adjustingGrid);
            adjustingIndex++;
        }
    }

    function beginAdjustColumn(e) {
        endAdjustColumn();
        startClientX = prevStartClientX = nextStartClientX = e.clientX;
        prevSwapOffset = nextSwapOffset = 15;
        adjudsting = e.target.tagName == "TD" ? e.target : $(e.target).parentsUntil(document.body, "td").get(0);
        adjustingGrid = $(adjudsting).parentsUntil(document.body, "table:first");
        adjustingHeader = $("tr:first", adjustingGrid);
        var cells = adjustingHeader.get(0).cells;
        for (adjustingIndex = 0; cells[adjustingIndex] != adjudsting
                    && adjustingIndex < cells.length; adjustingIndex++);
        $(document).mousemove(doAdjustColumn);
        $(document).mouseup(endAdjustColumn)
        $(document).bind("selectstart", cancelSelect);
        $(document.body).addClass('disable-select');
    }

    function endAdjustColumn() {
        if (shadow != null) shadow.remove();
        $(adjudsting).removeClass("grid-header-moving");
        $(document.body).removeClass('disable-select');
        shadow = null;
        adjudsting = null;
        adjustingGrid = null;
        adjustingHeader = null;
        $(document).unbind("mousemove", doAdjustColumn);
        $(document).unbind("mouseup", endAdjustColumn);
        $(document).unbind("selectstart", cancelSelect);
    }
    ns.ColumnAdjustable = function (gridID) {
        var grid = $("#" + gridID);
        columnOrderStorage.restore(grid);
        grid.find("tr:first").find("td").each(function () {
            $(this).mousedown(beginAdjustColumn);
        });
    };
    
    ns.Initialize = function(gridID){
        ns.Grouping(gridID);
        ns.ColumnAdjustable(gridID);
    }
})(window.jQuery, RegisterNamespace("Comm.PageGrid"));
